const Koa = require('koa');
const cors = require('@koa/cors');
const mysql = require('mysql2');
const wss = require('ws')
const path = require('path');
const static = require('koa-static');
const MqttClient = require('./MqttClient')
const { dbConfig, mqttConfig } = require('./config');

const app = new Koa();

// 需要创建config.js文件，并在其中配置数据库连接信息和MQTT连接信息
const connection = mysql.createConnection(dbConfig);

const mqttClientInstance = new MqttClient(mqttConfig, connection);

const {
    SQLTimeFrame,
    SQLExecute,
    UpdateOrder,
    InitOrder,
    processFieldsQuery,
    DataCount,
    Scenes,
    ScenesQuery,
    DeviceManager,
    SendHeadtopic,
    YOLO,
    sendDevices,
    SendData
} = require('./functions');
const { json } = require('stream/consumers');
const ws = new wss.Server({ port: 8080 });

let device = { id: 0 }
ws.on('connection', async (ws, res) => {
    console.log('客户端连接成功')
    switch (res.url) {
        case '/RealtimeData':
            // 监听客户端消息
            ws.on('message', (msg) => {
                let obj = JSON.parse(msg);
                console.log('客户端消息:', obj)
                if (obj.type === 'device') {
                    ScenesQuery(ws, connection, obj.d_type, obj.d_no);
                }
                else if (obj.type === 'saveimg') {
                    YOLO(connection, device.id, obj.base64)
                        .then(() => Scenes(ws, connection))
                        .catch(error => {
                            console.error('在处理 YOLO 请求时发生错误:', error);
                        });
                }
                else if (obj.type === 'power') {
                    SQLExecute(ws, connection, `SELECT AVG(field1)as I,AVG(field2)as V FROM t_other_data where (c_time between '${obj.startDate}' and '${obj.endDate}') ORDER BY id DESC`, "power");
                }
            })

            //初始化查询
            processFieldsQuery(ws, connection, "t_field_mapper", "t_data", "headtitle", "data", device.id);
            Scenes(ws, connection, device.id);
            SendData(ws, "current_device", device.id)

            setInterval(() => {
                processFieldsQuery(ws, connection, "t_field_mapper", "t_data", "headtitle", "data", device.id);
            }, 5000);

            break;
        case '/HistoryData':
            let his_sel = `SELECT id,d_no,field1,field2,field3,field4,DATE_FORMAT(c_time,'%Y-%m-%d %H:%i:%s') as c_time FROM t_data `
            let his_ord = `ORDER BY c_time DESC LIMIT 10 `
            ws.on('message', (msg) => {
                let obj = JSON.parse(msg);
                console.log('客户端消息:', obj)
                device.id = obj.id
                if (obj.type == "Page") {
                    let condition = ` where (c_time between '${obj.startDate}' and '${obj.endDate}') `
                    let offset = ` OFFSET ${obj.pageIndex} `
                    if (device.id != null) {
                        condition += `and d_no = ${device.id} `;
                    }
                    SQLExecute(ws, connection, his_sel + condition + his_ord + offset, "t_data")
                    DataCount(ws, connection, "t_data", "t_data_count", condition,false);
                }
                else if (obj.type == "device") {
                    ScenesQuery(ws, connection, obj.d_type, obj.d_no);
                }
                else if (obj.type === 'saveimg') {
                    YOLO(connection, device.id, obj.base64);
                    Scenes(ws, connection);
                }
                else if (obj.type === 'compelete') {
                    let condition = `where ${device.id} `
                    let offset = `OFFSET ${obj.pageIndex} `
                    SQLExecute(ws, connection, his_sel + condition + his_ord + offset, "t_data_compelete")
                }
                else if (obj.type === 'Yolo') {
                    let condition = ``;
                    if (obj.time != ''&& obj.time != null) {
                        condition = ` where DATE(c_time) = '${obj.time}'`;
                    }
                    SQLExecute(ws, connection, `SELECT d_no,field5,field6,field7,DATE_FORMAT(c_time,'%Y-%m-%d %H:%i:%s') as c_time FROM t_behavior_data ` + condition + "ORDER BY c_time DESC LIMIT 10", "yolo");
                    DataCount(ws, connection, "t_behavior_data", "yolo_count", condition,false);
                }
                else if (obj.type === 'delete') {
                    SQLExecute(ws, connection, `DELETE FROM t_data WHERE id = ${obj.id}`, "delete");
                }
                else if (obj.type === 'yoloPage') {
                    let condition = ``;
                    if(obj.time != null)
                    {
                        condition = ` where DATE(c_time) = '${obj.time}' `
                    }
                    SQLExecute(ws, connection, `SELECT d_no,field5,field6,field7,DATE_FORMAT(c_time,'%Y-%m-%d %H:%i:%s') as c_time FROM t_behavior_data` + condition + ` ORDER BY c_time DESC LIMIT 10 offset ${obj.pageIndex}`, "yolo");
                }

            })

            Scenes(ws, connection);
            DataCount(ws, connection, "t_data", "t_data_count");
            SQLExecute(ws, connection, his_sel + his_ord, "t_data");
            SendHeadtopic(ws, connection, "t_field_mapper");
            DataCount(ws, connection, "t_behavior_data", "yolo_count");

            break;
        case '/DataCompare':

            ws.on('message', (msg) => {
                let obj = JSON.parse(msg);
                console.log('客户端消息:', obj)
                let dcom_ord = `ORDER BY c_time DESC LIMIT ${obj.pageIndex} `
                if (obj.type === 'compelete') {
                    let dcom_sel = `SELECT d_no,${obj.fields},DATE_FORMAT(c_time,'%Y-%m-%d %H:%i:%s') as c_time FROM t_data `
                    let condition = `where ${obj.id} `
                    SQLExecute(ws, connection, dcom_sel + condition + dcom_ord, "t_data_compelete")
                }
            });
            sendDevices(ws, connection, "device");
            SendHeadtopic(ws, connection, "t_field_mapper");

            break;

        case '/ErrorData':
            let sel = `SELECT id,d_no,DATE_FORMAT(c_time,'%Y-%m-%d %H:%i:%s') as c_time,e_msg, e_no,type FROM t_error_msg `
            let ord = `ORDER BY c_time DESC LIMIT 10 `
            //处理消息
            ws.on('message', (msg) => {
                let obj = JSON.parse(msg);
                console.log('客户端消息:', obj)
                if (obj.type == "device") {
                    ScenesQuery(ws, connection, obj.d_type, obj.d_no);
                }
                else if (obj.type == "Page") {
                    let condition = `where (c_time between '${obj.startDate}' and '${obj.endDate}') `
                    let offset = `OFFSET ${obj.pageIndex}`
                    let d_no = obj.d_no
                    let e_no=``;
                    if (d_no != null) {
                        condition += `and e_no = ${d_no} `;
                        e_no = `and e_no = ${d_no} `;
                    }
                    SQLExecute(ws, connection, sel + condition + ord + offset, "t_error_msg")
                    DataCount(ws, connection, "t_error_msg", "t_error_msg_count", SQLTimeFrame('c_time', obj.startDate, obj.endDate)+e_no);
                }
                else if (obj.type === 'invade') {
                    let condition = `where (c_time between '${obj.startDate}' and '${obj.endDate}') and (type = '非法入侵')`
                    let offset = `OFFSET ${obj.pageIndex}`
                    SQLExecute(ws, connection, sel + condition + ord + offset, "t_error_msg")
                    DataCount(ws, connection, "t_error_msg", "t_error_msg_count", SQLTimeFrame('c_time', obj.startDate, obj.endDate));
                }
            });

            Scenes(ws, connection);
            DataCount(ws, connection, "t_error_msg", "t_error_msg_count");
            SQLExecute(ws, connection, sel + ord, "t_error_msg")

            break;
        case '/DeviceManager':
            ws.on('message', (msg) => {
                let obj = JSON.parse(msg);
                console.log('客户端消息:', obj)
                if (obj.type == "device") {
                    DeviceManager(ws, connection, device, obj.d_no);
                }
            });
            DeviceManager(ws, connection, device);

            break;
        case '/DirectConfig':
            //待重构
            let current_device = 0
            ws.on('message', (msg) => {
                let obj = JSON.parse(msg);
                console.log('客户端消息:', obj)
                if (obj.type == -1) {
                    UpdateOrder(msg, connection, mqttClientInstance, obj.d_no)
                    InitOrder(ws, connection)
                    SQLExecute(ws, connection, "SELECT *,DATE_FORMAT(c_time,'%Y-%m-%d %H:%i:%s') as c_time FROM t_operation_log ORDER BY c_time DESC LIMIT 10", "log");
                }
                else if (obj.type == "device") {
                    current_device = obj.d_no
                    InitOrder(ws, connection, current_device)
                }
                if (obj.type == "Page") {
                    SQLExecute(ws, connection, `SELECT *,DATE_FORMAT(c_time,'%Y-%m-%d %H:%i:%s') as c_time FROM t_operation_log ORDER BY c_time DESC LIMIT 10 OFFSET  ${obj.pageIndex}`, "log");
                }
            });
            Scenes(ws, connection);
            InitOrder(ws, connection);
            SQLExecute(ws, connection, "SELECT *,DATE_FORMAT(c_time,'%Y-%m-%d %H:%i:%s') as c_time FROM t_operation_log ORDER BY c_time DESC LIMIT 10", "log");
            DataCount(ws, connection, "t_operation_log", "log_count");

            break;
        default:
            break;
    }
});

app.use(cors({
    origin: '*'//允许所有域名访问
}));
app.use(static(path.join(__dirname, './src')))

app.listen(3000);
console.log('Server is running on port 3000');
console.log("服务器运行在 http://localhost:3000");